import {AbstractEntity} from "../basic/AbstractEntity";
import {Orientation} from "../basic/Orientation";
import {CoordinatesUtil} from "../../utils/CoordinatesUtil";
import {Position} from "../basic/Position";
import {KeyBoardState} from "../../core/KeyBoardState";
import {NumberUtil} from "../../utils/NumberUtil";
import {Game} from "../../core/Game";
import {IEntity} from "../basic/IEntity";
import {Bullet} from "./Bullet";
import {Drawer} from "../../core/Drawer";
import {Constants} from "../../core/Constants";

export class Tank extends AbstractEntity {


  //方形的体积
  static readonly drawSize: number = 50;


  /**
   * hit point
   */
  hp: number;

  /**
   * 所属玩家id
   */
  ownerId: number;

  /**
   * 移动速度X轴 当每秒逻辑帧为30时，每一个逻辑帧移动的像素点个数
   */
  speedX: number = 0;

  /**
   * 移动速度Y轴 当每秒逻辑帧为30时，每一个逻辑帧移动的像素点个数。详见move()
   */
  speedY: number = 0;

  /**
   * 最大速度
   */
  readonly maxSpeedPerSecond: number = Constants.tankDefaultMaxSpeedPerSecond;


  //每一帧中的最大速度
  maxSpeed: number;

  //每一帧中的加速度速度
  accelerationOfSpeed: number;
  /**
   * 加速度 每变化的速度值 用于加速或者减速
   */
  accelerationOfSpeedPerSecond: number = 30;

  /**
   * 旋转速度 单位为角度
   */
  rotateAngleSpeed: number;
  /**
   * 旋转速度 单位为角度
   */
  rotateAngleSpeedPerSecond: number = 360;
  playerKeyBoardState: KeyBoardState = new KeyBoardState();

  game: Game;

  /**
   * 上一次发射子弹的帧id 用于判断是否可以发射子弹
   *
   */
  lastShootFrame: number = 0;

  /**
   * 两次设计之间的间隔帧数
   */
  readonly shootFrameInterval: number;
  image: HTMLImageElement;


  constructor(logicPosition: Position, logicOrientation: Orientation, hp: number, ownerId: number, game: Game) {
    super(logicPosition, logicOrientation);
    this.hp = hp;
    this.ownerId = ownerId;
    this.game = game;
    this.maxSpeed = NumberUtil.resolved(this.maxSpeedPerSecond / game.logicFramePerSeconds);
    this.accelerationOfSpeed = NumberUtil.resolved(this.accelerationOfSpeedPerSecond / game.logicFramePerSeconds);
    this.rotateAngleSpeed = NumberUtil.resolved(this.rotateAngleSpeedPerSecond / game.logicFramePerSeconds);
    this.shootFrameInterval = NumberUtil.resolved(game.logicFramePerSeconds / Constants.tankShootBulletsPerSecond);
    this.image = new Image();
    this.image.src = "assets/img/tank.png";
    // this.image.src = "https://i04piccdn.sogoucdn.com/9ec099543addf06f";
  }

  override update() {
    super.update();
    this.changeSpeed();
    this.move();
    this.changeOrientation();
    // console.log('pos: ',this.drawPosition.x,this.drawPosition.y,this.logicPosition.x,this.logicPosition.y)

  }

  canShoot(currentFrame: number): boolean {
    return currentFrame - this.lastShootFrame >= this.shootFrameInterval;
  }

  onShoot(currentFrame: number) {
    this.lastShootFrame = currentFrame;
  }

  move() {
    if (this.speedX === 0 && this.speedY === 0) {
      return;
    }
    this.logicPosition = CoordinatesUtil.moveBySpeed(this.logicPosition, this.speedX, this.speedY);
  }

  changeOrientation() {
    const boardState = this.playerKeyBoardState;
    let angle: number = 0;

    let change = false;

    if (boardState.aPress) {
      angle = 270;
      change = true;
    }
    if (boardState.sPress) {
      angle = 180;
      change = true;
    }

    if (boardState.wPress) {
      angle = 0;
      change = true;
    }
    if (boardState.dPress) {
      angle = 90;
      change = true;
    }

    //左下
    if (boardState.aPress && boardState.sPress) {
      angle = 180 + 45;
    }
    //右上
    if (boardState.wPress && boardState.dPress) {
      angle = 45;
    }
    //右下
    if (boardState.dPress && boardState.sPress) {
      angle = 90 + 45;
    }
    //左上
    if (boardState.aPress && boardState.wPress) {
      angle = 270 + 45;
    }
    if (change) {
      const orientation = new Orientation(NumberUtil.resolved(angle));
      orientation.normalize();
      this.logicOrientation.rotateToTarget(orientation, this.rotateAngleSpeed);
    }

  }

  changeSpeed() {
    let spdx: number = 0;

    const modify = 4;
    /**
     * 这里/modify是为了加强速度抑制器手感，如果想快速减速，应该按反方向键急停
     */
    if (this.playerKeyBoardState.aPress == this.playerKeyBoardState.dPress) {
      spdx = NumberUtil.closeToNumber(this.speedX, this.accelerationOfSpeed / modify, 0);
    } else {
      //向右加速
      if (this.playerKeyBoardState.dPress) {
        spdx = NumberUtil.closeToNumber(this.speedX, this.accelerationOfSpeed, this.maxSpeed);

        //向左加速
      } else {
        spdx = NumberUtil.closeToNumber(this.speedX, this.accelerationOfSpeed, -this.maxSpeed);
      }
    }


    let spdy: number = this.speedY;
    if (this.playerKeyBoardState.wPress == this.playerKeyBoardState.sPress) {
      spdy = NumberUtil.closeToNumber(this.speedY, this.accelerationOfSpeed / modify, 0);
    } else {
      //向上加速
      if (this.playerKeyBoardState.wPress) {
        spdy = NumberUtil.closeToNumber(this.speedY, this.accelerationOfSpeed, -this.maxSpeed);
        //向下加速
      } else {
        spdy = NumberUtil.closeToNumber(this.speedY, this.accelerationOfSpeed, this.maxSpeed);
      }
    }


    //保证斜向速度看起来正常
    const speedXY = Math.sqrt(spdx * spdx + spdy * spdy);
    if (this.maxSpeed < speedXY) {
      const reducePercent = (speedXY - this.maxSpeed) / this.maxSpeed;
      spdx *= (1 - reducePercent);
      spdy *= (1 - reducePercent);
    }
    this.speedX = NumberUtil.resolved(spdx);
    this.speedY = NumberUtil.resolved(spdy);
  }

  shouldRemove(): boolean {
    return this.hp <= 0;
  }

  /**
   * 两个坦克相撞 需要进行速度的处理。
   * @param one
   * @param other
   */
  static onTanksCollide(one: Tank, other: Tank) {
    const speedY1 = one.speedY;
    const speedX1 = one.speedX;

    const speedY2 = other.speedY;
    const speedX2 = other.speedX;

    one.speedX = (speedX1 + speedX2) / 2;
    one.speedY = (speedY1 + speedY2) / 2;

    other.speedY = one.speedY;
    other.speedX = one.speedX;

    //修改距离 防止互相镶嵌
    const distance = Position.distance(one.logicPosition, other.logicPosition);
    if (distance < Tank.drawSize) {
      const vectorTo = one.logicPosition.vectorTo(other.logicPosition);
      const distanceX = Math.abs(other.logicPosition.x - one.logicPosition.x);
      one.logicPosition.x -= distanceX / 2 * vectorTo.x;
      other.logicPosition.x += distanceX / 2 * vectorTo.x;

      const distanceY =Math.abs( other.logicPosition.y - one.logicPosition.y);
      one.logicPosition.y -= distanceY / 2 * vectorTo.y;
      other.logicPosition.y += distanceY / 2 * vectorTo.y;
    }

  }

  override onCollide(other: IEntity): void {
    super.onCollide(other);
    if (other instanceof Tank) {
      // this.hp -= 10;
    } else if (other instanceof Bullet) {
      this.hp -= other.damage;
    }
  }

  getSize(): number {
    return Tank.drawSize;
  }

  draw(ctx: CanvasRenderingContext2D): void {


    const drawHpX = this.drawPosition.x - Tank.drawSize / 2;
    const drawHpY = this.drawPosition.y - Tank.drawSize ;
    //hp绘制不需要旋转朝向
    this.drawTankHp(ctx, drawHpX, drawHpY, this.hp);

    Drawer.defaultEntityDraw(ctx, this.image, this.drawPosition, this.drawOrientation, Tank.drawSize);
  }

  drawTankHp(ctx: CanvasRenderingContext2D, x: number, y: number, hp: number) {
    ctx.save();
    ctx.font='16px'
    ctx.fillStyle='blue'
    ctx.fillText('hp: '+String(hp), x, y, 30);
    ctx.restore();
  }

}
